﻿using DotNetCore.CAP;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using NP.BPMReportPlatform.Common;
using NP.BPMReportPlatform.DBHelper;
using NP.BPMReportPlatform.EmailHelper;
using NP.BPMReportPlatform.Entities.BPM_Business;
using NP.BPMReportPlatform.Entities.BPM_Business.CXYXTHNR;
using NP.BPMReportPlatform.Entities.BPM_Engine;
using NP.BPMReportPlatform.Entities.BPM_Platform;
using NP.BPMReportPlatform.Entities.BPM_TodoCentre;
using NP.BPMReportPlatform.RecurringJobs.Dto.YCLWLJGZSYC;
using NP.BPMReportPlatform.RecurringJobs.Dto;
using NP.BPMReportPlatform.Utilities;
using NP.Enterprise.Utils.Http;
using Serilog;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DocumentFormat.OpenXml.Drawing;
using System.Numerics;

namespace NP.BPMReportPlatform.RecurringJobs
{
    public class CXYXTHNRRecurringJob : BpmReportPlatformRecurringJob, ICXYXTHNRRecurringJob
    {
        private readonly SqlSugarClient _db, _dbPlatform, _dbEngine, _dbProcess, _dbTodoCenter;
        private readonly INPRestHttpHelper _nPRestHttp;
        private readonly IConfiguration _configuration;
        private readonly ILogger _logger;
        private readonly IEmailAPPService _emailAPPService;
        private readonly ICapPublisher _capBus;
        private IHostingEnvironment _env;
        private readonly string TestEmail = "yangxin@movit-tech.com";
        private readonly ICommonService _commonService;

        public CXYXTHNRRecurringJob(
            ISqlSugarAppService sqlSugarAppService,
            IConfiguration configuration,
            INPRestHttpHelper nPRestHttp,
            ILogger logger,
            IEmailAPPService emailAPPService,
            ICapPublisher capBus,
            IHostingEnvironment env,
            ICommonService commonService)
        {
            _db = sqlSugarAppService.GetBusinessInstance();
            _dbPlatform = sqlSugarAppService.GetPlatformInstance();
            _dbEngine = sqlSugarAppService.GetEngineInstance();
            _dbProcess = sqlSugarAppService.GetProcessInstance();
            _dbTodoCenter = sqlSugarAppService.GetToDoCenterInstance();
            _nPRestHttp = nPRestHttp;
            _configuration = configuration;
            _logger = logger;
            _emailAPPService = emailAPPService;
            _capBus = capBus;
            _env = env;
            _commonService = commonService;
        }

        /// <summary>
        /// 通知发起人和高新办审批人，提前一个月通知 合作计划，费用支付时限，到期时间
        /// </summary>
        /// <returns></returns>
        public async Task DoJob()
        {
            _logger.Information("CXYXTHNRRecurringJob DoTask Start");
            try
            {
                await PlanNotice();

                await FundNotice();
            }
            catch (Exception ex)
            {
                _logger.Information($"CXYXTHNRRecurringJob DoTask Error:{ex.Message}");
            }

            _logger.Information("CXYXTHNRRecurringJob DoTask End");
        }

        private async Task PlanNotice()
        {
            var limitDay = DateTime.Today.AddMonths(1).AddDays(1);
            var dataList = await _db.Queryable<CXYXTHNRHeader, CXYXTHNRImplementPlan, BusinessProcessesNew>(
                 (a, b, c) => a.InstanceNumber == b.InstanceNumber && a.InstanceNumber == c.InstanceId)
                 .Where((a, b, c) => b.DataType == 1 && b.EndTime < limitDay && b.EndTime > DateTime.Today
                 && b.PushStatus == 0 && SqlFunc.ToInt32(a.StepNum) > 3 &&
                 (c.ProcessStatusCode == "approved" || c.ProcessStatusCode == "processing")).Select((a, b) => new {
                     a.AddUserId,
                     a.AddUserName,
                     b.Id,
                     b.InstanceNumber,
                     b.PushStatus,
                     b.DataType,
                     b.EndTime,
                     b.Stage,
                     b.StartTime,
                     b.PaymentAmount
                 }).Distinct().ToListAsync();

            var title = $"产学研活动管理流程合作计划到期前提醒{(_env.IsProduction() ? "" : "【测试环境】")}";
            var gxbUserLoginIds = await _db.Queryable<KeyValues>().Where(x =>
                x.CatalogCode == "CXYXTHNRNoticeUser").Select(x => x.Name).Distinct().FirstAsync();
            var gxbUserLoginIdList = !string.IsNullOrWhiteSpace(gxbUserLoginIds) ?
                gxbUserLoginIds.Split(",", StringSplitOptions.RemoveEmptyEntries).ToList() : new List<string>();
            var instanceNumbers = dataList.Select(x => x.InstanceNumber).Distinct().ToList();
            var tasks = await _dbTodoCenter.Queryable<ToDoCenterTask>()
                .Where(x => instanceNumbers.Contains(x.BusinessNumber))
                .Select(x => new { x.BusinessNumber, x.TaskId }).Distinct().ToListAsync();
            var addUserIds = dataList.Select(x => x.AddUserId).Distinct().ToList();
            var addUsers = await _dbPlatform.Queryable<Users>()
                .Where(x => addUserIds.Contains(x.UserId) && x.Status == 1)
                .Select(x => new { x.UserId, x.UserLoginId, x.WorkNumber, x.Email })
                .Distinct().ToListAsync();
            var gxbUsers = await _dbPlatform.Queryable<Users>()
                .Where(x => gxbUserLoginIdList.Contains(x.UserLoginId) && x.Status == 1)
                .Select(x => new { x.UserId, x.UserLoginId, x.WorkNumber, x.Email }).ToListAsync();
            var needUpdateIds = new List<Guid>();
            foreach (var data in dataList)
            {
                var task = tasks.FirstOrDefault(x => x.BusinessNumber == data.InstanceNumber);

                if (task == null)
                {
                    continue;
                }

                var wxUsers = new List<string>();
                var emails = new List<string>();
                //高新办配置用户
                if (gxbUsers.Any())
                {
                    wxUsers.AddRange(gxbUsers.Select(x => x.UserLoginId));
                    emails.AddRange(gxbUsers.Select(x => x.Email));
                }
                // 发起人
                var addUser = addUsers.FirstOrDefault(x => x.UserId == data.AddUserId);
                if (addUser != null)
                {
                    wxUsers.Add(addUser.UserLoginId);
                    emails.Add(addUser.Email);
                }

                if (!wxUsers.Any())
                {
                    continue;
                }

                var endTime = data.EndTime.Value.ToString(DateFormatHelper.DateFormat);
                var mobileUrl = GetProcessMobileUrl(data.InstanceNumber, task.TaskId.ToString());
                var pcUrl = GetProcessToDoUrl(data.InstanceNumber);
                await _commonService.MsgSendForAPI(title,
                    $"您好，您在BPM平台上的产学研活动管理流程(流水编号：{data.InstanceNumber})" +
                    $"合作计划阶段还有一个月到期，请及时处理。结束日期：{endTime}",
                    mobileUrl, GetToWxCode(wxUsers.JoinAsString("|")));

                emails = emails.Distinct().ToList();
                foreach (var email in emails)
                {
                    var content = $"您好，您在BPM平台上的产学研活动管理流程(流水编号：{data.InstanceNumber})，合作计划阶段还有一个月到期，请及时处理。<br />";
                    content += $"结束日期：{endTime}<br />";
                    content += $"计划内容：{data.Stage}<br />";
                    content += $"流程链接：<a href='{pcUrl}' target='_blank'>点击链接</a>";
                    await SendNoticeEmail(title, content, email);
                }

                needUpdateIds.Add(data.Id);
            }

            await _db.Updateable<CXYXTHNRImplementPlan>()
                .SetColumns(x => new CXYXTHNRImplementPlan { PushStatus = 1 })
                .Where(x => needUpdateIds.Contains(x.Id)).ExecuteCommandAsync();
        }

        private async Task FundNotice()
        {
            var limitDay = DateTime.Today.AddMonths(1).AddDays(1);
            var dataList = await _db.Queryable<CXYXTHNRHeader, CXYXTHNRImplementPlan, BusinessProcessesNew>(
                 (a, b, c) => a.InstanceNumber == b.InstanceNumber && a.InstanceNumber == c.InstanceId)
                 .Where((a, b, c) => b.DataType == 2 && b.EndTime < limitDay && b.EndTime > DateTime.Today
                 && b.PushStatus == 0 && SqlFunc.ToInt32(a.StepNum) > 3 &&
                 (c.ProcessStatusCode == "approved" || c.ProcessStatusCode == "processing")).Select((a, b) => new {
                     a.AddUserId,
                     a.AddUserName,
                     b.Id,
                     b.InstanceNumber,
                     b.PushStatus,
                     b.DataType,
                     b.EndTime,
                     b.Stage,
                     b.StartTime,
                     b.PaymentAmount
                 }).Distinct().ToListAsync();

            var title = $"产学研活动管理流程费用支付时限到期前提醒{(_env.IsProduction() ? "" : "【测试环境】")}";
            var gxbUserLoginIds = await _db.Queryable<KeyValues>().Where(x =>
                x.CatalogCode == "CXYXTHNRNoticeUser").Select(x => x.Name).Distinct().FirstAsync();
            var gxbUserLoginIdList = !string.IsNullOrWhiteSpace(gxbUserLoginIds) ?
                gxbUserLoginIds.Split(",", StringSplitOptions.RemoveEmptyEntries).ToList() : new List<string>();
            var instanceNumbers = dataList.Select(x => x.InstanceNumber).Distinct().ToList();
            var tasks = await _dbTodoCenter.Queryable<ToDoCenterTask>()
                .Where(x => instanceNumbers.Contains(x.BusinessNumber))
                .Select(x => new { x.BusinessNumber, x.TaskId }).Distinct().ToListAsync();
            var addUserIds = dataList.Select(x => x.AddUserId).Distinct().ToList();
            var addUsers = await _dbPlatform.Queryable<Users>()
                .Where(x => addUserIds.Contains(x.UserId) && x.Status == 1)
                .Select(x => new { x.UserId, x.UserLoginId, x.WorkNumber, x.Email })
                .Distinct().ToListAsync();
            var gxbUsers = await _dbPlatform.Queryable<Users>()
                .Where(x => gxbUserLoginIdList.Contains(x.UserLoginId) && x.Status == 1)
                .Select(x => new { x.UserId, x.UserLoginId, x.WorkNumber, x.Email }).ToListAsync();
            var needUpdateIds = new List<Guid>();
            foreach (var data in dataList)
            {
                var task = tasks.FirstOrDefault(x => x.BusinessNumber == data.InstanceNumber);

                if (task == null)
                {
                    continue;
                }

                var wxUsers = new List<string>();
                var emails = new List<string>();
                //高新办配置用户
                if (gxbUsers.Any())
                {
                    wxUsers.AddRange(gxbUsers.Select(x => x.UserLoginId));
                    emails.AddRange(gxbUsers.Select(x => x.Email));
                }
                // 发起人
                var addUser = addUsers.FirstOrDefault(x => x.UserId == data.AddUserId);
                if (addUser != null)
                {
                    wxUsers.Add(addUser.UserLoginId);
                    emails.Add(addUser.Email);
                }

                if (!wxUsers.Any())
                {
                    continue;
                }

                var endTime = data.EndTime.Value.ToString(DateFormatHelper.DateFormat);
                var mobileUrl = GetProcessMobileUrl(data.InstanceNumber, task.TaskId.ToString());
                var pcUrl = GetProcessToDoUrl(data.InstanceNumber);
                await _commonService.MsgSendForAPI(title,
                    $"您好，您在BPM平台上的产学研活动管理流程(流水编号：{data.InstanceNumber}）" +
                    $"费用支付时限还有一个月到期，请及时处理。结束日期：{endTime}",
                    mobileUrl, GetToWxCode(wxUsers.JoinAsString("|")));

                emails = emails.Distinct().ToList();
                foreach (var email in emails)
                {
                    var content = $"您好，您在BPM平台上的产学研活动管理流程(流水编号：{data.InstanceNumber}），费用支付时限还有一个月到期，请及时处理。<br />";
                    content += $"结束日期：{endTime}<br />";
                    content += $"支付金额：{data.PaymentAmount}<br />";
                    content += $"流程链接：<a href='{pcUrl}' target='_blank'>点击链接</a>";
                    await SendNoticeEmail(title, content, email);
                }

                needUpdateIds.Add(data.Id);
            }

            await _db.Updateable<CXYXTHNRImplementPlan>()
                .SetColumns(x => new CXYXTHNRImplementPlan { PushStatus = 1 })
                .Where(x => needUpdateIds.Contains(x.Id)).ExecuteCommandAsync();
        }

        private async Task SendNoticeEmail(string topic, string replaceContent, string email)
        {
            var content = "";
            var templateName = "CXYXTHNRNotice.cshtml";

            if (!string.IsNullOrEmpty(templateName))
            {
                content = _emailAPPService.GenerateEmailTemplate(templateName);
                content = !string.IsNullOrEmpty(replaceContent) ?
                    content.Replace("{content}", replaceContent) : string.Empty;
            }
            if (!string.IsNullOrEmpty(content) && !string.IsNullOrEmpty(email))
            {
                await _capBus.PublishAsync("bpmnew.EmailAppService.SendEmailAsync",
                  new SendEmailSimpleDto()
                  {
                      To = GetToEmails(email),
                      Subject = topic,
                      Body = content,
                  });
            }
        }

        private string GetToEmails(string emails)
        {
            return _env.IsProduction() ? emails : TestEmail;
        }

        private string GetToWxCode(string WxCode)
        {
            return _env.IsProduction() ? WxCode : "yangxin.mt";
        }

        /// <summary>
        /// 获取流程查看页面的地址(企业微信)
        /// </summary>
        /// <param name="instanceNumber">流程实例编号</param>
        /// <param name="taskId">taskId</param>
        /// <returns></returns>
        private string GetProcessMobileUrl(string instanceNumber, string taskId)
        {
            var pUrl = string.Format(_configuration["BPM:MobileUrlTemplate"], instanceNumber, taskId);
            return pUrl;
        }

        private string GetProcessToDoUrl(string instanceNumber)
        {
            var pUrl = string.Format(_configuration["BPM:NoAuthPCProcessUrl"], instanceNumber);
            return pUrl;
        }
    }
}
